home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
keyb
/
rbkeyswp.zip
/
RBKEYSWP.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-06-22
|
9KB
|
233 lines
;**************************************************************************
;* *
;* RBkeyswap v2.0 6/22/91 *
;* (c) Copyright 1989, 1991 Ralf Brown *
;* *
;* Permission is granted to redistribute unmodified copies in their *
;* entirety. Modified copies may be distributed provided that they *
;* are clearly marked as modified and the original unmodified source *
;* code is distributed together with the modification. *
;* *
;* ------------------------------------------------------------------ *
;* *
;* RBkeyswap is a program to fix the IBM's enhanced keyboard, which *
;* places the Escape, Control, and CapsLock keys in the wrong places. *
;* After running RBkeyswap, Escape and `/~ will be exchanged, as will *
;* the left control key and the CapsLock key. The right control key *
;* will be unaffected. *
;* *
;* RBkeyswap loads itself high (no need for LOADHI or LH) into either *
;* an XMS upper memory block or a DOS 5.0 UMB. If neither is avail- *
;* able, RBkeyswap will go resident in low memory, using just 128 *
;* bytes (it needs a mere 64 bytes in high memory). Note that it will *
;* use 272 bytes under DOS 2.x, because those versions force all TSRs *
;* to leave at least that much resident. *
;* *
;* You need a BIOS which provides the keyboard intercept on INT 15h. *
;* If your BIOS does not support this, RBkeyswap will merely use up *
;* memory without doing anything. *
;* *
;* Usage: RBKEYSWP *
;* Note: the program does not check whether it is already installed, *
;* so a second run will re-swap the keys, negating the action and *
;* using up a small amount of extra memory. *
;* *
;* ------------------------------------------------------------------ *
;* *
;* Rebuilding RBkeyswap: *
;* TASM RBKEYSWP *
;* TLINK /T RBKEYSWP *
;* *
;**************************************************************************
code segment 'code'
assume cs:code
org 2Ch
envseg dw ? ; segment address of our environment
org 100h
RBkeyswap:
jmp init
banner db 13,"RBkeyswap 2.0",9,"(c) Copyright 1989, 1991 Ralf Brown",13,10
db "Swaps Esc/tilde and CapsLock/LeftCtrl",13,10,"$"
db 26 ; stop output here if TYPEing the .COM file
;--------------------------------------------------------------------------
int15_handler:
jnc not_ours ; has a previous handler said to ignore scan code?
cmp ah,4Fh ; scan code translation?
jne not_ours ; if not, chain immediately
cmp al,0E1h ; is it a special key such as "Pause"?
je int15_setbranch
cmp al,0E0h ; or a right-{alt,ctrl}?
_branch: ; (if prev scan was E0h or E1h, we will
BRANCH equ (_branch-int15_handler) ; branch unconditionally)
je int15_setbranch ; the opcode here gets toggled between
; JE and JMP SHORT as needed
shl al,1 ; move break bit into CF
pushf ; and remember it for later
cmp al,1Dh*2 ; ctrl?
je ctrl_or_capslock
cmp al,3Ah*2 ; capslock?
je ctrl_or_capslock
cmp al,01h*2 ; ESC?
je esc_or_tilde
cmp al,29h*2 ; backquote/tilde key?
jne int15_no_xlat
esc_or_tilde:
xor al,0Fh*2 ; (AL xor 0F) xor 27 == (AL xor 28h)
; 01h -> 29h, 29h -> 01h
; thus esc and tilde swapped
ctrl_or_capslock:
xor al,27h*2 ; 1Dh -> 3Ah, 3Ah -> 1Dh
; thus left-ctrl and capslock swapped
int15_no_xlat:
popf ; retrieve break bit in CF
rcr al,1 ; and add to translated scan code
jmp short int15_done
int15_setbranch:
xor byte ptr cs:BRANCH,(74h xor 0EBh) ; toggle between JE and JMP
int15_done:
stc ; use the scan code
not_ours:
db 0EAh ; FAR JMP chain to previous handler
old_int15 dd ?
end_resident label byte
code_size equ $ - int15_handler
resident_code equ (code_size + 15)/16
;--------------------------------------------------------------------------
xms_entry dd 0
resident_seg dw 0 ; location of interrupt handler after relocation
resident_size dw 0 ; number of paras to keep on going TSR
alloc_strat dw 0
link_state db 0 ; are UMBs part of memory chain?
exit_func db 4Ch ; will change to 31h if we must go resident
assume ds:code
init:
mov dx,offset banner
mov ah,9
int 21h ; identify ourself
mov ax,3515h
int 21h ; get old vector
mov word ptr old_int15,bx ; and store in new interrupt handler
mov word ptr old_int15 + 2,es
; first, see if we can load into an XMS upper memory block
mov ax,352Fh
int 21h ; find out whether INT 2F is valid
mov ax,es
or ax,bx ; don't try XMS if INT 2F is NULL
jz no_XMS ; (could be case under DOS 2.x)
mov ax,4300h ; see if XMS is installed
int 2Fh
cmp al,80h ; did XMS respond?
jnz no_XMS
mov ax,4310h ; if XMS present, get its entry point
int 2Fh
mov word ptr xms_entry,bx
mov word ptr xms_entry+2,es ; and store entry point for call
mov ah,10h ; request UMB
mov dx,resident_code ; this is how much we need
call xms_entry ; ask XMS for the memory
cmp ax,1 ; did we get it?
jne no_XMS ; if not, try DOS 5 UMB
mov resident_seg,bx ; remember where we'll relocate
jmp relocate_handler ; and go install
; if no XMS, try a DOS5 UMB
no_XMS:
mov ax,3000h ; get DOS version
int 21h
cmp al,5 ; DOS 5.0 or higher?
jb not_dos5
cmp al,10 ; but make sure not OS/2 penalty box
jae not_dos5
mov ax,5802h ; get UMB link state
int 21h
mov link_state,al ; and remember it for later restore
mov ax,5803h ; set link state
mov bx,1 ; UMBs are part of memory chain
int 21h
mov ax,5800h ; get allocation strategy
int 21h
mov alloc_strat,ax ; and remember it for later restore
mov ax,5801h ; set allocation strategy
mov bx,40h ; alloc high memory only
int 21h
mov ah,48h ; allocate memory
mov bx,resident_code ; this is how much we need
int 21h ; try to allocate the UMB
pushf ; remember whether we succeeded
jc no_highmem ; did we succeed?
mov resident_seg,ax ; yes, so remember where to relocate
dec ax ; address the MCB for our new memory
mov es,ax ; block
mov word ptr es:[1],0Ah ; make DOS owner of UMB, so it won't be
mov word ptr es:[8],"CS" ; released when we exit (details below)
;---------------------------
; Reasons for mucking with the MCB:
; DOS 5 will release any memory blocks owned by the program when
; it exits without going TSR, even if the blocks are in high memory
; and high memory has been disconnected from the memory chain. So,
; we need to change the owner field such that DOS thinks it belongs to
; somebody else and doesn't release it when we exit. Both 08h and
; 0Ah are used by DOS itself, so we know they won't be messed with.
; However, the DOS 5 MEM program gets confused by 08h, because it
; thinks the block should have subblocks, which it doesn't. 0Ah is
; normally a locked-out portion of high memory, so there aren't any
; problems there. I put "SC" in the name field to make DOS think
; this is "system code".
;---------------------------
no_highmem:
mov ax,5801h
mov bx,alloc_strat ; restore allocation strategy
int 21h
mov ax,5803h ; restore link state
mov bh,0
mov bl,link_state
int 21h
popf ; get back whether we were successful
jnc relocate_handler ; if successful, go install
; as a last resort, use our own PSP to store the code, and go resident
not_dos5:
mov ax,cs
add ax,4 ; copy to offset 40h in PSP
mov resident_seg,ax
mov exit_func,31h ; TSR rather than normal exit
mov ah,49h ; since we will be going resident,
mov es,envseg ; discard our environment
int 21h
mov envseg,0 ; and zero the ptr in the PSP
mov resident_size,resident_code + 4
relocate_handler:
; relocate interrup